1. /* ldbl2ary.cpp by K.Tsuru */
  2. /*****************************
  3. SN class's auxiliary function
  4. long double --> DRADIX conversion
  5. ******************************/
  6. #ifndef SN_H
  7. #include "sn.h"
  8. #endif
  9. /*
  10. It gets the values of "e" and "d" which satisfy a condition
  11. p = d * 10^e (0.1 =< d < 1.0 ).
  12. Note that even if p = 1.0*10^e, *d = 0.999999999... and becomes one by adding
  13. DBL_EPSILON to that.
  14. */
  15. static int dblExp(ldouble p, ldouble* d){
  16. ldouble absp = fabs(p); // check |p| == 1.0 or 0.1
  17. if(absp == 1.0){ // 1.0 = 0.1 * 10^1
  18. *d = p > 0.0 ? 0.1 : -0.1; return 1;
  19. } else if(absp == 0.1){ // 0.1
  20. *d = p > 0.0 ? 0.1 : -0.1; return 0;
  21. }
  22. ldouble q = log10(absp);
  23. int e = (int)q, e_add = 0;
  24. if(q >= 0.0) e++;
  25. if(e > DBL_MAX_10_EXP){ absp /= 10.0; e--; e_add = 1; }
  26. if(e) q = absp*pow(10.0, -e);
  27. else q = absp;
  28. if( q + DBL_EPSILON >= 1.0){// q = 0.99999999...*10^e = 0.1 * 10^(e+1)
  29. q = 0.1; e++;
  30. } else if( q < 0.1){ // q = 0.09999999.... *10^e = 0.1*10^e
  31. q = 0.1;
  32. }
  33. *d = p > 0.0 ? q : -q;
  34. return e + e_add;
  35. }
  36. /*
  37. It converts "d" to fType array "ary" where 0.1 =< d < 1.0 and return the size.
  38. */
  39. static uint ConvertfType(FigBlock& ary, ldouble d){
  40. int j, len = 0, r;
  41. fType under = 0, round = 0;
  42. for(j = 0; (d > 0.0) && (len <= DOUBLE_FIG); j++){
  43. ary[j] = (fType)d;
  44. d -= (ldouble)ary[j];
  45. d *= (ldouble)DRADIX;
  46. len += DFIGURES;
  47. }
  48. ary[j] = (d >= 1.0) ? (fType)d : 0;
  49. r = len - DOUBLE_FIG;
  50. if(r > 0 && ary[j]){
  51. under = 1;
  52. while(r){ // r > 0 then under >= 10
  53. under *= 10; r--;
  54. }
  55. //Check last "r" figures.
  56. round = ary[j] % under; // ary[j] = 8999, under = 10, round = 9
  57. if(round >= under/2 ){ // 9 > 10/2 = 5
  58. ary[j] -= round; // ary[j] = 8990
  59. ary[j] += under; // ary[j] = 8990 + 10 = 9900
  60. } else round = 0;
  61. }
  62. if(round){
  63. int k;
  64. for(k = j; k > 0 ; k--){ // normalize
  65. if(ary[k] < DRADIX) break;
  66. else {
  67. ary[k-1]++;
  68. ary[k] = 0; //len -= DFIGURES;
  69. }
  70. }
  71. if(k < j) under = 0;
  72. j = k;
  73. }
  74. if(under){ //cut out last figure
  75. ary[j] /= under; ary[j] *= under;
  76. }
  77. while(!ary(j) && j) j--;//some low figures becomes zero by round
  78. if(ary(0)) return 1; //d = 0.9999999999 -> d = 1.0 ( ary(0) = 1 )
  79. return (uint)j+1;
  80. }
  81. /**********************************************************
  82. main body
  83. Provides radix conversion ldouble "x" to res[] in DRADIX.
  84. It returns the value of exponent.
  85. ***********************************************************/
  86. int ldoubleToArray(ldouble x, FigBlock& res, uint *size){
  87. res.reserve(minArraySize-1);
  88. res[0] = res[1] = 0;
  89. *size = 2;
  90. // x == 0.0 ?
  91. if(x == 0.0) return 0;
  92. ldouble absX = fabs(x);
  93. int exp;
  94. ldouble ip, dp;
  95. dp = modf(absX, &ip);
  96. if(dp + DBL_EPSILON >= 1.0){
  97. dp = 0.0; ip = ip + 1.0;
  98. }
  99. //An integer which has an order of "DRADIX" can be exactly represented by ldouble.
  100. //Then "+ROUND_DBL_INT" is not nesessary.
  101. if( (dp == 0.0) && (ip < (ldouble)DRADIX ) ){//integer of one figure
  102. res[1] = (fType)ip;
  103. return 1;
  104. }
  105. res.reserve(DOUBLE_FIG/DFIGURES+3);
  106. ldouble d;
  107. exp = dblExp(absX, &d); // absX = d*10^exp, 0.1 <= d < 1.0
  108. fType p10;
  109. int dexp, r;
  110. uint sz = ConvertfType(res, d);
  111. if(sz == 1){ // d = 0.9999999999 -> d = 1.0
  112. res[0] = 0; res[1] = DRADIX/10;
  113. sz = 2; exp++; //do not return to settle the value of "exp"
  114. }
  115. dexp = exp/DFIGURES;
  116. r = exp - dexp*DFIGURES;
  117. if(r > 0){ r -= DFIGURES; dexp++; } //r <= 0
  118. p10 = 1;
  119. while(r < 0){ p10 *= 10; r++; }
  120. uint j;
  121. if(p10 > 1){ //divide by p10
  122. res.reserve(sz);
  123. res[sz] = 0; sz++;
  124. ulong w, u;
  125. u = 0;
  126. for(j = 1; j < sz; j++){
  127. w = u*DRADIX +(ulong)res[j];
  128. res[j] = fType(w/p10);
  129. u = w%p10;
  130. }
  131. }
  132. j = sz-1;
  133. #ifndef NDEBUG
  134. res(j);
  135. #endif
  136. while(res[j] == 0) j--;
  137. *size = j+1;
  138. return dexp;
  139. }

ldbl2ary.cpp : last modifiled at 2017/08/20 12:01:29(3,854 bytes)
created at 2017/10/03 15:00:51
The creation time of this html file is 2017/10/07 10:54:15 (Sat Oct 07 10:54:15 2017).